
#include "NodeInstance.h"

// [*] and_or_tree::CBasicInstance

bool and_or_tree::CBasicInstance::InputFromStream(istream& inStream)
{
	if (inStream>>x>>y)
		return true;
	else
		return false;
}

void and_or_tree::CBasicInstance::OutputToStream(ostream& outStream, bool fUseShortFormat) const
{
	if (fUseShortFormat)
	{
		outStream<<'\t'<<(int)(x);
		outStream<<'\t'<<(int)(y);
	}
	else
	{
		outStream.precision(16);
		outStream<<'\t'<<showpos<<scientific<<x;
		outStream<<'\t'<<showpos<<scientific<<y;
	}
}

// [*] and_or_tree::CParsedInstance

double and_or_tree::CParsedInstance::S_MinPositionDifference;
double and_or_tree::CParsedInstance::S_MinRotationDifference;
double and_or_tree::CParsedInstance::S_MinScaleDifference;

and_or_tree::CParsedInstance::CParsedInstance()
{
	ClearAll();
}

void and_or_tree::CParsedInstance::ClearAll()
{
	x = y = 0.0;
	rotation = scale = 0.0;
	Tag = 0;
	ClearScore();
}

void and_or_tree::CParsedInstance::ClearScore()
{
	node_shape_score = node_appearance_score = node_total_score = 0.0;
	tree_shape_score = tree_appearance_score = tree_total_score = 0.0;
}

void and_or_tree::CParsedInstance::RefreshTotalScore()
{
	node_total_score = node_shape_score + node_appearance_score;
	tree_total_score = tree_shape_score + tree_appearance_score;
}

bool and_or_tree::CParsedInstance::InputFromStream(istream& inStream)
{
	bool ret = true;
	ret = ret && (inStream>>x>>y>>rotation>>scale);
	ret = ret && (inStream>>Tag);
	ret = ret && (inStream>>node_shape_score>>node_appearance_score>>tree_shape_score>>tree_appearance_score);
	node_total_score = node_shape_score + node_appearance_score;
	tree_total_score = tree_shape_score + tree_appearance_score;
	return ret;
}

void and_or_tree::CParsedInstance::OutputToStream(ostream& outStream, bool fUseShortFormat) const
{
	CBasicInstance::OutputToStream(outStream, fUseShortFormat);

	if (fUseShortFormat)
	{
		outStream.precision(3);
		outStream<<'\t'<<fixed<<rotation*180.0/PI;
		outStream<<'\t'<<fixed<<exp(scale);
	}
	else
	{
		outStream.precision(16);
		outStream<<'\t'<<showpos<<scientific<<rotation;
		outStream<<'\t'<<showpos<<scientific<<scale;
	}

	outStream<<'\t'<<Tag;

	if (fUseShortFormat)
	{
		outStream.precision(6);
		outStream<<'\t'<<fixed<<node_shape_score;
		outStream<<'\t'<<fixed<<node_appearance_score;
		outStream<<'\t'<<fixed<<tree_shape_score;
		outStream<<'\t'<<fixed<<tree_appearance_score;
	}
	else
	{
		outStream.precision(16);
		outStream<<'\t'<<showpos<<scientific<<node_shape_score;
		outStream<<'\t'<<showpos<<scientific<<node_appearance_score;
		outStream<<'\t'<<showpos<<scientific<<tree_shape_score;
		outStream<<'\t'<<showpos<<scientific<<tree_appearance_score;
	}
}

bool and_or_tree::CParsedInstance::AreSameByInstance(const CParsedInstance& a, const CParsedInstance& b)
{
	double t;
	
	t = CMyMath::sqr(a.x - b.x) + CMyMath::sqr(a.y - b.y);
	if (t > CMyMath::sqr(S_MinPositionDifference)) return false;

	t = fabs(CMyMath::FormatAngle(a.rotation - b.rotation));
	if (t > S_MinRotationDifference) return false;

	t = fabs(a.scale - b.scale);
	if (t > S_MinScaleDifference) return false;

	return true;
}

bool and_or_tree::CParsedInstance::CompareByTreeScore_Smaller(const CParsedInstance& a, const CParsedInstance& b)
{
	return a.tree_total_score < b.tree_total_score;
}

bool and_or_tree::CParsedInstance::CompareByTreeScore_Bigger(const CParsedInstance& a, const CParsedInstance& b)
{
	return a.tree_total_score > b.tree_total_score;
}

// [*] and_or_tree::CRichInstance

and_or_tree::CRichInstance::CRichInstance()
{
	Clear();
}

void and_or_tree::CRichInstance::Clear()
{
	this->x = this->y = 0.0;
	OrientationList.Clear();
	LengthList.Clear();
}

int and_or_tree::CRichInstance::ComputeOffset_SingleChild(int ChildIndex) const
{
	//In fact it is ComputeOffset_ChildrenPair(ChildIndex, ChildIndex)
	return (ChildrenAmount + ChildrenAmount - ChildIndex + 1) * ChildIndex / 2;
}

int and_or_tree::CRichInstance::ComputeOffset_ChildrenPair(int ChildIndexA, int ChildIndexB) const
{
	int t;
	if (ChildIndexA > ChildIndexB) { t = ChildIndexA; ChildIndexA = ChildIndexB; ChildIndexB = t; }
	return (ChildrenAmount + ChildrenAmount - ChildIndexA - 1) * ChildIndexA / 2 + ChildIndexB;
}

void and_or_tree::CRichInstance::SetChildrenAmount(int ChildrenAmount)
{
	this->ChildrenAmount = ChildrenAmount;
	int zz = (ChildrenAmount + 1) * ChildrenAmount / 2;
	OrientationList.Resize(zz); OrientationList.Fill(0.0);
	LengthList.Resize(zz); LengthList.Fill(0.0);
}

void and_or_tree::CRichInstance::InitAll(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList, double x, double y)
{
	SetChildrenAmount((int)ChildrenPtrList.Size);
	Compute_PC_Pairs(ChildrenPtrList, x, y);
	Compute_CC_Paris(ChildrenPtrList);
}

void and_or_tree::CRichInstance::InitAll(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList)
{
	int i;
	const CBasicInstance * const * qqi;
	double tx = 0.0;
	double ty = 0.0;
	ChildrenAmount = (int)ChildrenPtrList.Size;
	for ( qqi = ChildrenPtrList.pElement, i = 0; i < ChildrenAmount; ++i, ++qqi )
	{
		tx += (*qqi)->x;
		ty += (*qqi)->y;
	}
	InitAll(ChildrenPtrList, tx / ChildrenAmount, ty / ChildrenAmount);
}

void and_or_tree::CRichInstance::Init_CC_Pairs(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList)
{
	SetChildrenAmount((int)ChildrenPtrList.Size);
	this->x = 0.0; this->y = 0.0;
	Compute_CC_Paris(ChildrenPtrList);
}

void and_or_tree::CRichInstance::Compute_PC_Pairs(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList)
{
	int i, t;
	double tx, ty, tt;
	const CBasicInstance * const * qqi;
	double* pOri = OrientationList.pElement;
	double* pLen = LengthList.pElement;

	for ( qqi = ChildrenPtrList.pElement, i = 0; i < ChildrenAmount; ++i, ++qqi )
	{
		t = ComputeOffset_SingleChild(i);
		tx = x - (*qqi)->x; ty = y - (*qqi)->y;

		tt = CMyMath::FormatAngle(atan2(ty, tx));
		pOri[t] = tt;
		tt = sqrt(tx * tx + ty * ty); if (tt < 1.0) tt = 1.0;
		pLen[t] = tt;
	}
}

void and_or_tree::CRichInstance::Compute_PC_Pairs(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList, double x, double y)
{
	this->x = x; this->y = y;
	Compute_PC_Pairs(ChildrenPtrList);
}

void and_or_tree::CRichInstance::Compute_CC_Paris(const CSimpleTypeArray<const CBasicInstance*>& ChildrenPtrList)
{
	int i, j, t;
	double tx, ty, tt;
	const CBasicInstance * const * qqi;
	const CBasicInstance * const * rrj;
	double* pOri = OrientationList.pElement;
	double* pLen = LengthList.pElement;

	for ( qqi = ChildrenPtrList.pElement, i = 0; i < ChildrenAmount; ++i, ++qqi )
		for ( rrj = ChildrenPtrList.pElement + i + 1, j = i + 1; j < ChildrenAmount; ++j, ++rrj )
		{
			t = ComputeOffset_ChildrenPair(i, j);
			tx = (*rrj)->x - (*qqi)->x; ty = (*rrj)->y - (*qqi)->y;

			tt = CMyMath::FormatAngle(atan2(ty, tx));
			pOri[t] = tt;
			tt = sqrt(tx * tx + ty * ty); if (tt < 1.0) tt = 1.0;
			pLen[t] = tt;
		}
}

void and_or_tree::CRichInstance::InitAll(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList, double x, double y)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	InitAll(TempBiptrList, x, y);
}

void and_or_tree::CRichInstance::InitAll(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	InitAll(TempBiptrList);
}

void and_or_tree::CRichInstance::Init_CC_Pairs(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	Init_CC_Pairs(TempBiptrList);
}

void and_or_tree::CRichInstance::Compute_PC_Pairs(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	Compute_PC_Pairs(TempBiptrList);
}

void and_or_tree::CRichInstance::Compute_PC_Pairs(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList, double x, double y)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	Compute_PC_Pairs(TempBiptrList, x, y);
}

void and_or_tree::CRichInstance::Compute_CC_Paris(const CSimpleTypeArray<const CParsedInstance*>& ChildrenPtrList)
{
	int i, ii = (int)ChildrenPtrList.Size;
	const CParsedInstance * const * qqpi = ChildrenPtrList.pElement;
	CSimpleTypeArray<const CBasicInstance*> TempBiptrList;
	TempBiptrList.Resize(ii);
	const CBasicInstance * * ppbi = TempBiptrList.pElement;
	for ( i = 0; i < ii; ++i ) *(ppbi++) = *(qqpi++);

	Compute_CC_Paris(TempBiptrList);
}

// [*] and_or_tree::CInstanceChoice

and_or_tree::CInstanceChoice::CInstanceChoice()
{
	fIsfake = fHasFakeChildren = false;
	ClearScore();
	ClearChildrenChoices();
}

void and_or_tree::CInstanceChoice::ClearChildrenChoices(int ChildrenAmount)
{
	ChildrenChoiceIndexList.Resize(ChildrenAmount);
	ChildrenChoiceIndexList.Fill(0);
}

bool and_or_tree::CInstanceChoice::InputFromStream(istream& inStream)
{
	bool ret = true;
	ret = ret && (CParsedInstance::InputFromStream(inStream));
	ret = ret && (inStream>>fIsfake>>fHasFakeChildren);
	int tt;
	ChildrenChoiceIndexList.Clear();
	for ( ; ret; )
	{
		ret = ret && (inStream>>tt);
		if (!ret || tt==-1) break;
		ChildrenChoiceIndexList.PushBack(tt);
	}
	return ret;
}

void and_or_tree::CInstanceChoice::OutputToStream(ostream& outStream, bool fUseShortFormat) const
{
	CParsedInstance::OutputToStream(outStream, fUseShortFormat);
	outStream<<'\t'<<fIsfake;
	outStream<<'\t'<<fHasFakeChildren;
	int i;
	outStream<<'\t';
	for ( i = 0; i < (int)ChildrenChoiceIndexList.Size; ++i )
		outStream<<ChildrenChoiceIndexList.pElement[i]<<' ';
	outStream<<"-1";
}

